#include "anatomicallink.h"

AnatomicalLink::AnatomicalLink(AnatomicalRegion *rA, AnatomicalRegion *rB, double c)
{
    actor = vtkActor::New();
    mapper = vtkPolyDataMapper::New();
    actor->SetMapper(mapper);
    regA = rA;
    regB = rB;
    corr = c;
	dist = -1;
	enabled = true;
    init();
}

/*AnatomicalLink::AnatomicalLink(const AnatomicalLink &link)
{
    actor = link.actor;
    mapper = link.mapper;
    regA = link.regA;
    regB = link.regB;
    corr = link.corr;
}

AnatomicalLink& AnatomicalLink::operator=(const AnatomicalLink& link)
{
    actor = link.actor;
    mapper = link.mapper;
    regA = link.regA;
    regB = link.regB;
    corr = link.corr;
    return *this;
}*/

bool AnatomicalLink::operator==(AnatomicalLink aLink)
{
    return this->equals(&aLink);
}

AnatomicalLink::~AnatomicalLink()
{
    /*if(actor)
        actor->Delete();
    if(mapper)
        mapper->Delete();
        */
}

AnatomicalRegion* AnatomicalLink::regionA()
{
    return regA;
}

AnatomicalRegion* AnatomicalLink::regionB()
{
    return regB;
}

void AnatomicalLink::setCorrelation(double c)
{
    corr = c;
    double rgb[3] = {0, 0, 0};
	ColorMap::getInstance()->getLookupTable()->GetColor(c,rgb);
	actor->GetProperty()->SetColor(rgb[0],rgb[1],rgb[2]);
	tubeFilt->SetRadius(15*abs(corr));
	tubeFilt->Update();
	mapper->Update();
}

void AnatomicalLink::setColor(const double* &col)
{
    color[0] = col[0];
    color[1] = col[1];
    color[2] = col[2];
}

void AnatomicalLink::setVisible(bool visible)
{
    if(visible)
        actor->VisibilityOn();
    else
        actor->VisibilityOff();
}

void AnatomicalLink::setEnabled(bool enable)
{
	enabled = enable;
}

bool AnatomicalLink::isEnabled()
{
	return enabled;
}

bool AnatomicalLink::isSymmetry()
{
	//the link is built up such that regionA always has a lower id than regionB
	//so we can safely make this assumption
	return regA->info().RegionID == regB->info().RegionID-1; 
}

double AnatomicalLink::correlation() const
{
    return corr;
}

bool AnatomicalLink::equals(AnatomicalLink* other)
{
    return regA->equals(other->regionA()) &&
            regB->equals(other->regionB()) &&
            corr == other->correlation();
}

void AnatomicalLink::init()
{
    mapper->RemoveAllInputs();

    vtkLineSource *lsrc = vtkLineSource::New();
    double pAx = regA->info().CenterX;
    double pBx = regB->info().CenterX;
    double pAy = regA->info().CenterY;
    double pBy = regB->info().CenterY;
    double pAz = regA->info().CenterZ;
    double pBz = regB->info().CenterZ;
    lsrc->SetPoint1(pAx,pAy,pAz);
    lsrc->SetPoint2(pBx,pBy,pBz);
    lsrc->Update();

    tubeFilt = vtkTubeFilter::New();
    tubeFilt->SetInput(lsrc->GetOutput());
    tubeFilt->SetNumberOfSides(10);

    tubeFilt->SetRadius(15*abs(corr));
    tubeFilt->Update();

    if(mapper->GetInput())
        mapper->GetInput()->Delete();

    mapper->SetInput(tubeFilt->GetOutput());
	mapper->SetScalarRange(regA->info().RegionID,regB->info().RegionID);
    mapper->Update();
	
	double rgb[3] = {0, 0, 0};
	ColorMap::getInstance()->getLookupTable()->GetColor(corr,rgb);
	actor->GetProperty()->SetColor(rgb[0],rgb[1],rgb[2]);
	actor->VisibilityOff();

    tubeFilt->Delete();
    lsrc->Delete();

}

void AnatomicalLink::attachToRenderer(vtkRenderer* renderer)
{
    renderer->AddActor(actor);
    regA->NodeRefCount = regA->NodeRefCount+1;
    regB->NodeRefCount = regB->NodeRefCount+1;
}

void AnatomicalLink::detachFromRenderer(vtkRenderer* renderer)
{
    renderer->RemoveActor(actor);
    regA->NodeRefCount = regA->NodeRefCount-1;
    regB->NodeRefCount = regB->NodeRefCount-1;

    if(regA->NodeRefCount==0)
        renderer->RemoveActor(regA->getNodeActor());

    if(regB->NodeRefCount==0)
        renderer->RemoveActor(regB->getNodeActor());
}

double AnatomicalLink::distance()
{
	if(dist == -1) //not yet calculated
	{
		double x1 = regA->info().CenterX - regB->info().CenterX;
		double y1 = regA->info().CenterY - regB->info().CenterY;
		double z1 = regA->info().CenterZ - regB->info().CenterZ;
		dist = sqrt(pow(x1,2)+pow(y1,2)+pow(z1,2)) / 10.0;
	}
	return dist;
}